using Agron.Data.Contracts;
using Agron.Services.Contracts;

using System;
using System.ServiceModel;
using System.Web.Security;


namespace Agron.Services.Behaviors
{
    /// <summary>
    /// Implements the <see cref="IMembershipService"/> service contract.
    /// </summary>
    [ServiceBehavior]
    public class MembershipService : IMembershipService
    {
        /// <summary>
        /// Verifies that the supplied user name and password are valid.
        /// </summary>
        /// <param name="username">The name of the user to be validated.</param>
        /// <param name="password">The password for the specified user.</param>
        /// <returns>
        /// true if the supplied user name and password are valid; otherwise, false.
        /// </returns>
        [OperationBehavior]
        public bool ValidateUser(string username, string password)
        {
            if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");
            if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password");

            return Membership.ValidateUser(username, password);
        }

        /// <summary>
        /// Gets the information from the data source for the specified membership user.
        /// </summary>
        /// <param name="username">The name of the user to be validated.</param>
        /// <returns>
        /// A <see cref="UserProfile"/> object representing the user.
        /// </returns>
        [FaultContract(typeof(UserNotFoundException)), OperationBehavior]
        public UserProfile GetUserProfileByUserName(string username)
        {
            if (string.IsNullOrEmpty(username)) throw new ArgumentNullException("username");

            MembershipUser membershipUser = Membership.GetUser(username);
            if (null == membershipUser)
                throw new InvalidOperationException("user not found");

            return DecorateMembershipUserAsUserProfile(membershipUser);
        }

        /// <summary>
        /// Gets the information from the data source for the specified membership user using a database identifier.
        /// </summary>
        /// <param name="userId"></param>
        /// <returns>
        /// A <see cref="UserProfile"/> object representing the user.
        /// </returns>
        [FaultContract(typeof(UserNotFoundException)), OperationBehavior]
        public UserProfile GetUserProfileByUserId(Guid userId)
        {
            MembershipUser membershipUser = Membership.GetUser(userId);
            if (null == membershipUser)
                throw new UserNotFoundException();

            return DecorateMembershipUserAsUserProfile(membershipUser);
        }

        /// <summary>
        /// Updates the database with the information for the specified user.
        /// </summary>
        /// <param name="userProfile">A <see cref="UserProfile"/> object that represents the user to be updated and the updated information for the user.</param>
        /// <exception cref="ArgumentNullException"><paramref name="userProfile"/> is null.</exception>
        [OperationBehavior]
        public void UpdateUserProfile(UserProfile userProfile)
        {
            if (null == userProfile)
                throw new ArgumentNullException("userProfile");

            MembershipUser membershipUser = Membership.GetUser(userProfile.UserId);
            if (null == membershipUser)
                throw new InvalidOperationException();

            membershipUser.Comment = userProfile.DisplayName;
            membershipUser.Email = userProfile.Email;

            Membership.UpdateUser(membershipUser);
        }

        private static UserProfile DecorateMembershipUserAsUserProfile(MembershipUser membershipUser)
        {
            UserProfile userProfile = new UserProfile();
            userProfile.DisplayName = membershipUser.Comment;
            userProfile.Email = membershipUser.Email;
            userProfile.UserId = (Guid) membershipUser.ProviderUserKey;
            userProfile.Username = membershipUser.UserName;

            return userProfile;
        }
    }
}
